#include "Model.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <GL/gl.h>

using namespace std;

std::ostream &operator<< (std::ostream &output, Face_obj &f) {
	output << f.v[0] << "/" << f.vt[0] << "/" << f.vn[0] << " ";
	output << f.v[1] << "/" << f.vt[1] << "/" << f.vn[1] << " ";
	output << f.v[2] << "/" << f.vt[2] << "/" << f.vn[2];

	return output;
}

Model::Model() {
}

Model::Model (std::string obj_path) {
	LoadOBJFile(obj_path);
}

void Model::Draw() {
	int i;
	VectorXYZ tempvec;

	for (i = 0; i < (int)faces.size(); i++) {
		glBegin(GL_TRIANGLES); 
			glColor3f(1.0f,0.0f,0.0f);
			tempvec = vertices[(faces[i].v[0])];
			glVertex3f( tempvec.x, tempvec.y, tempvec.z); 
			
			glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
			tempvec = vertices[(faces[i].v[1])];
			glVertex3f( tempvec.x, tempvec.y, tempvec.z); 
			
			glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
			tempvec = vertices[(faces[i].v[2])];
			glVertex3f( tempvec.x, tempvec.y, tempvec.z); 
		glEnd();
	}
}

void Model::Draw(VectorXYZ position, VectorXYZ orientation, VectorXYZ up, float scale) {
	int i, j;
	VectorXYZ tempvec = orientation;
	tempvec.Normalize();
	
	for (i = 0; i < (int)faces.size(); i++) {
		glBegin(GL_TRIANGLES);

		for (j = 0; j < 3; j++) {
			// Colour (for differentiation)
			if (j == 0)
				glColor3f(1.0f,0.0f,0.0f);
			if (j == 1)
				glColor3f(0.0f,1.0f,0.0f);
			if (j == 2)
				glColor3f(0.0f,0.0f,1.0f);

			// Loading correct vertice
			tempvec = vertices[(faces[i].v[j])];

			// Rotating vertex to orientation/up based co-ordinate system
			tempvec.set( tempvec.x * (orientation % up)
						+ tempvec.y * up
						- tempvec.z * orientation );

			// Scaling vertice
			tempvec *= scale;
			
			// Translating vertice
			tempvec = tempvec + position;

			// Drawing vertice
			glVertex3f( tempvec.x, tempvec.y, tempvec.z); 
		}
		
		glEnd();
	}
}

void Model::LoadOBJFile(std::string obj_path) {
	string OBJpath = ROOT_OBJ_PATH + obj_path;
	ifstream LoadStream;

	string LoadLine;
	float LoadNo;
	int tempint;
	VectorXYZ tempvec;
	Face_obj tempface;

	LoadStream.open(OBJpath);
	if (!LoadStream.is_open()) {
		cout << "Failed to open file :: " << OBJpath << endl;
		system("pause");
		exit(0);
	}
	else {
		cout << "Loading Model: " << OBJpath <<  endl;
		while (!LoadStream.eof()) {
			if (!LoadStream.good()) {
				break;
			}

			getline(LoadStream, LoadLine);
			if (!LoadLine.empty()) {
				if (LoadLine.at(0) == 'v') {
					if (LoadLine.at(1) == ' ') {
						// Vertex Found
						LoadLine.erase(0, 3);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.x = LoadNo;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.y = LoadNo;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.z = LoadNo;

						vertices.push_back(tempvec);
					}
					else if (LoadLine.at(1) == 'n') {
						// Vertice Normal Found
						LoadLine.erase(0, 3);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.x = LoadNo;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.y = LoadNo;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempvec.z = LoadNo;

						vertex_normals.push_back(tempvec);
					}
					else if (LoadLine.at(1) == 't') {
						// Vertice Texture Point Found
						
					}
				}
				else if (LoadLine.at(0) == 'f') {
					// Face found

					LoadLine.erase(0, 1);

					for (int i = 0; i < 3; i++) {
						LoadLine.erase(0, 1);

						tempint = LoadLine.find_first_of('/');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempface.v[i] = (int)LoadNo - 1;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of('/');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempface.vt[i] = (int)LoadNo - 1;

						LoadLine.erase(0, tempint+1);
						tempint = LoadLine.find_first_of(' ');
						LoadNo = (float)atof((LoadLine.substr(0, tempint)).c_str());
						tempface.vn[i] = (int)LoadNo - 1;

						LoadLine.erase(0, tempint);
					}

					faces.push_back(tempface);
				}
			}
		}
	}
}